#pragma once

#include <fstream>
#include <iostream>

#include "aes.h"
#include "cJSON.h"

/*!
 * @brief 音乐元数据
*/
class NeteaseMusicMetadata
{
private:
    std::string mAlbum;   // 专辑
    std::string mArtist;  // 艺术家
    std::string mFormat;  //格式
    std::string mName;    // 歌曲名称
    int mDuration = 0;    //持续时间
    int mBitrate = 0;     // 比特率

private:
    cJSON* mRaw{};

public:
    NeteaseMusicMetadata(cJSON*);
    ~NeteaseMusicMetadata();
    const std::string& Name() const { return mName; }
    const std::string& Album() const { return mAlbum; }
    const std::string& Artist() const { return mArtist; }
    const std::string& Format() const { return mFormat; }
    const int Duration() const { return mDuration; }
    const int Bitrate() const { return mBitrate; }
};

/*!
 * @brief ncm 解密; cryptography 密码学
*/
class NeteaseCrypt
{
public:
    NeteaseCrypt(std::string const&);
    ~NeteaseCrypt();

private:
    static const unsigned char _sCoreKey[17];
    static const unsigned char _sModifyKey[17];
    static const unsigned char _mPng[8];
    enum NcmFormat
    {
        MP3,
        FLAC
    };

public:
    const std::string& FilePath() const { return _mFilepath; }
    const std::string& DumpFilePath() const { return _mDumpFilepath; }

private:
    std::string _mFilepath;
    std::string _mDumpFilepath;
    NcmFormat _mFormat;
    char* _mImageData = nullptr;
    size_t _mImageLen = 0;
    std::ifstream _mFile;
    unsigned char _mKeyBox[256];
    NeteaseMusicMetadata* _mMetaData{};

private:
    bool IsNcmFile();
    bool OpenFile(std::string const&);
    std::streamsize Read(std::istream::char_type* s, std::streamsize n);
    void BuildKeyBox(unsigned char* key, int keyLen);
    std::string MimeType(const char* data);

public:
    void EndianSwap(unsigned int& x);
    void Dump();  // 解密 mp3 data
    void FixMetadata();
};
